計算機實驗室之樹莓派:課程 2 OK02
OK02 課程構建於 OK01 課程的基礎上,通過不停地打開和關閉 OK 或 ACT LED 指示燈來實現閃爍。假設你已經有了 課程 1:OK01 操作系統的代碼,它將是這一節課的基礎。
1、等待
等待是操作系統開發中非常有用的部分。操作系統經常發現自己無事可做,以及必須要延遲。在這個例子中,我們希望通過等待,讓 LED 燈打開、關閉的閃爍可以看到。如果你只是打開和關閉它,你將看到這個視覺效果,因為計算機每秒種可以打開和關閉它好幾千次(LCTT 譯註:視覺暫留效應會使你難以發覺它的閃爍)。在後面的課程中,我們將看到精確的等待,但是現在,我們只要簡單地去消耗時間就足夠了。
mov r2,#0x3F0000
wait1$:
sub r2,#1
cmp r2,#0
bne wait1$
sub reg,#val
從寄存器reg
中的值上減去數字val
cmp reg,#val
將寄存器中的值與數字val
進行比較。如果最後的比較結果是不相等,那麼執行後綴了
ne
的b
命令。
上面是一個很常見的產生延遲的代碼片段,由於每個樹莓派基本上是相同的,所以產生的延遲大致也是相同的。它的工作原理是,使用一個 mov
命令將值 3F0000 16 推入到寄存器 r2
中,然後將這個值減 1,直到這個值減到 0 為止。在這裡使用了三個新命令 sub
、 cmp
和 bne
。
sub
是減法命令,它只是簡單地從第一個參數中的值減去第二個參數中的值。
cmp
是個很有趣的命令。它將第一個參數與第二個參數進行比較,然後將比較結果記錄到一個稱為當前處理器狀態寄存器的專用寄存器中。你其實不用擔心它,它記住的只是兩個數誰大或誰小,或是相等而已。 1
bne
其實是一個偽裝的分支命令。在 ARM 彙編語言家族中,任何指令都可以有條件地運行。這意味著如果上一個比較結果是某個確定的結果,那個指令才會運行。這是個非常有意思的技巧,我們在後面將大量使用到它,但在本案例中,我們在 b
命令後面的 ne
後綴意思是 「只有在上一個比較的結果是值不相等,才去運行該分支」。ne
後綴可以使用在任何命令上,其它幾個(總共 16 個)條件也是如此,比如 eq
表示等於,而 lt
表示小於。
2、組合到一起
上一節講我提到過,通過將 GPIO 地址偏移量設置為 28(即:str r1,[r0,#28]
)而不是 40 即可實現 LED 的關閉。因此,你需要去修改課程 OK01 的代碼,在打開 LED 後,運行等待代碼,然後再關閉 LED,再次運行等待代碼,並包含一個回到開始位置的分支。注意,不需要重新啟用 GPIO 的 16 號針腳的輸出功能,這個操作只需要做一次就可以了。如果你想更高效,我建議你復用 r1
寄存器的值。所有課程都一樣,你可以在 下載頁面 找到所有的解決方案。需要注意的是,必須保證你的所有標籤都是唯一的。當你寫了 wait1$:
你其它行上的標籤就不能再使用 wait1$
了。
在我的樹莓派上,它大約是每秒閃兩次。通過改變我們所設置的 r2
寄存器中的值,可以很輕鬆地修改它。但是,不幸的是,我不能夠精確地預測它的運行速度。如果你的樹莓派未按預期正常工作,請查看我們的故障排除頁面,如果它正常工作,恭喜你。
在這個課程中,我們學習了另外兩個彙編命令:sub
和 cmp
,同時學習了 ARM 中如何實現有條件運行。
在下一個課程,課程 3:OK03 中我們將學習如何編寫代碼,以及建立一些代碼復用的標準,並且如果需要的話,可能會使用 C 或 C++ 來寫代碼。
- 如果你點了這個鏈接,說明你一定想知道它的具體內容。CPSR 是一個由許多獨立的比特位組成的 32 比特寄存器。它有一個位用於表示正數、零和負數。當一個
cmp
指令運行後,它從第一個參數上減去第二個參數,然後用這個位記下它的結果是正數、零還是負數。如果是零意味著它們相等(a-b=0
暗示著a=b
)如果為正數意味著 a 大於 b(a-b>0
暗示著a>b
),如果為負數意味著小於。還有其它比較指令,但cmp
指令最直觀。 ↩
via: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/ok02.html
作者:Robert Mullins 選題:lujun9972 譯者:qhwdw 校對:wxy
本文轉載來自 Linux 中國: https://github.com/Linux-CN/archive